/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       abstract_creature.h

	$Header: /game/creature_stack.h $

	$NoKeywords: $

 ************************************************************************/

#ifndef ABSTRACT_CREATURE_H_INCLUDED
#define ABSTRACT_CREATURE_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#pragma warning( disable: 4786 )

#include "bitmap_layer_ptr.h"
#include "combat_actor_model_cache.h"
#include "has_defense.h"

class t_abstract_grail_data_source;
class t_artifact;
enum  t_artifact_slot;
enum  t_creature_ability;
enum  t_creature_type;
class t_hero;
enum  t_missile_type;
enum  t_skill_mastery;
enum  t_skill_type;
enum  t_spell;
enum  t_terrain_type;
enum  t_town_type;

// -----------------------------------------------------------------------
// base class for creatures in combat and on the adventure map.  Used for 
// functions which work with either.
// -----------------------------------------------------------------------
class t_abstract_creature : public virtual t_has_defense
{
public:
	virtual ~t_abstract_creature();

	virtual bool				can_cast( t_spell spell ) const = 0;
	bool						can_cast_spells() const;
	virtual t_town_type         get_alignment() const = 0;
	virtual t_artifact const&	get_artifact( t_artifact_slot slot ) const = 0;
	virtual int					get_backpack_count() const = 0;
	virtual t_artifact const&	get_backpack_slot( int slot ) const = 0;
	virtual t_hero const*		get_const_hero() const = 0;
	virtual int					get_combat_movement() const = 0;
	virtual t_creature_type     get_creature_type() const = 0;
	virtual int					get_damage_high() const = 0;
	virtual int					get_damage_low() const = 0;
	float						get_damage_modifier( t_has_defense const&	defender,
													 bool					ranged ) const;
	float						get_damage_modifier( t_has_defense const&	defender,
													 bool					ranged,
													 float					offense ) const;
	virtual	float				get_defense_reduction( bool ranged ) const = 0;
	virtual int                 get_experience_value( int number = -1 ) const = 0;
	t_hero*						get_hero();
	t_hero const*				get_hero() const;
	virtual int					get_hit_points() const = 0;
	virtual int                 get_luck() const = 0;
	virtual std::string			get_name( bool include_article = false, int number = -1 ) const = 0;
	virtual int			        get_maximum_spell_points() const = 0;
	virtual int					get_number() const = 0;
	virtual float				get_offense( bool ranged ) const = 0;
	virtual t_bitmap_layer_ptr	get_portrait( int height = 52, bool force_awake_portrait = false ) const = 0;
	int							get_range_effect( int range, bool obscured ) const;
	virtual int					get_shots() const = 0;
	virtual t_skill_mastery		get_skill( t_skill_type skill ) const = 0;
	virtual int					get_speed() const = 0;
	virtual int                 get_spell_cost( t_spell spell ) const = 0;
	virtual int                 get_spell_power( t_spell spell, t_abstract_grail_data_source const & grail_data, int number = -1 ) const = 0;
	virtual int					get_spell_points() const = 0;
	virtual bool                is_native_terrain( t_terrain_type terrain ) const;
	virtual bool                has_ability( t_creature_ability ability ) const = 0;
	virtual bool                knows_spell( t_spell spell ) const = 0;
	virtual t_artifact			remove_backpack( int slot ) = 0;
};

inline float t_abstract_creature::get_damage_modifier( t_has_defense const&	defender,
													   bool					ranged ) const
{
	return get_damage_modifier( defender, ranged, get_offense( ranged ));
}


inline t_hero const* t_abstract_creature::get_hero() const
{
	return get_const_hero();
}

inline t_hero* t_abstract_creature::get_hero() 
{
	return const_cast<t_hero*>( get_const_hero() );
}

#endif // ABSTRACT_CREATURE_H_INCLUDED